package com.zenchn.controller;

import com.google.common.collect.ImmutableMap;
import com.zenchn.annotation.OperLog;
import com.zenchn.entity.*;
import com.zenchn.enums.AlidayuSmsEnum;
import com.zenchn.enums.OperLogActionEnum;
import com.zenchn.enums.SessionAttributeEnum;
import com.zenchn.exception.CheckException;
import com.zenchn.external.service.AliSmsApiService;
import com.zenchn.external.service.FileGenericStrategy;
import com.zenchn.model.*;
//import com.zenchn.redis.service.MobilePhoneCaptchaRedisService;
import com.zenchn.service.*;
import com.zenchn.utils.CheckStrength;
import com.zenchn.utils.CommonUtils;
import com.zenchn.utils.PwdHashSaltUtils;
import com.zenchn.utils.RegexKit;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.LinkedList;
import java.util.Map;
import java.util.Objects;

/**
 * 当前登录账户 相关功能控制层
 *
 * @author dingxinfa
 * @date 2018-08-16
 */
@RestController
@RequestMapping(value = "current")
@Api(value = "当前登录账户-我的-相关接口", tags = "我的-相关接口")
@RequiresAuthentication
public class CurrentController {

    private final String MODULE = "个人管理>用户信息";

    @Resource
    private SysFileService sysFileService;

    @Resource
    private DictService dictService;

    @Resource
    private AccountService accountService;

    @Resource
    private FileGenericStrategy fileGenericStrategy;

//    @Resource
//    private MobilePhoneCaptchaRedisService captchaRedisService;

    @Resource
    private AliSmsApiService aliSmsApiService;

    @Resource
    private SysConfig sysConfig;

    @Resource
    private AreasService areasService;

    @Resource
    private RegionService regionService;

    /***
     * 文件保存临时目录
     */
    @Value("${custom.file.temp.path}")
    private String tmpPath;


    /**
     * 获取登录账号信息
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "获取登录账号信息", isSaveRequestData = false)
    @ApiOperation(value = "获取登录账号信息", notes = "获取登录账号信息")
    @GetMapping(value = "/accountInfo")
    public ResponseEntity<HttpDataResult<TSysAccountVO>> accountInfo(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<TSysAccountVO> result = new HttpDataResult<>(request.getRequestURI());

        final TSysAccount currAccount = (TSysAccount) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_INFO.getKey());
        final TMiAccountExtend accountExtend = (TMiAccountExtend) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_EXTEND_INFO.getKey());
        TSysAccountVO accountVO = new TSysAccountVO();
        BeanUtils.copyProperties(currAccount, accountVO);

        //设置账户扩展信息
        if (accountExtend != null) {
            accountVO.setAccountLevel(accountExtend.getAccountLevel());
            accountVO.setAreasCode(accountExtend.getAreasCode());
            accountVO.setRegionCode(accountExtend.getRegionCode());
            accountVO.setAgentTarget(accountExtend.getAgentTarget());
            accountVO.setAgentL2Target(accountExtend.getAgentL2Target());
            accountVO.setAgentL3Target(accountExtend.getAgentL3Target());
            accountVO.setHospitalTarget(accountExtend.getHospitalTarget());
            accountVO.setHospitalL2Target(accountExtend.getHospitalL2Target());
            accountVO.setHospitalL3Target(accountExtend.getHospitalL3Target());
            //设置所属省份名称
            if (accountExtend.getAreasCode() != null) {
                TSysAreas areas = areasService.selectByPrimaryKey(accountExtend.getAreasCode());
                if (areas != null) {
                    accountVO.setAreasCodeName(areas.getName());
                }
            }
            //设置所属区域名称
            if (accountExtend.getRegionCode() != null) {
                TMiRegion region = regionService.selectByPrimaryKey(accountExtend.getRegionCode());
                if (region != null) {
                    accountVO.setRegionCodeName(region.getRegionName());
                }
            }
            //设置用户等级名称
            TSysDict dict = dictService.selectByPrimaryKey(accountExtend.getAccountLevel());
            if (dict != null) {
                accountVO.setAccountLevelName(dict.getDictName());
            }
        }


        /***************登录人头像 * start***************/
        if (null != currAccount.getPortraitFileId() && !"".equals(currAccount.getPortraitFileId())) {
            TSysFile sf = sysFileService.selectByPrimaryKey(currAccount.getPortraitFileId());
            if (null!=sf) {
                String portraitUrl = sysConfig.getCurrentUseFormalFileUrl() + "/" + sf.getFilePath();
                request.getSession().setAttribute(SessionAttributeEnum.PORTRAIT_URL.getKey(), portraitUrl);
                accountVO.setPortraitUrl(portraitUrl);
            }
        }
        /***************登录人头像 * start***************/

        TSysDict postType = dictService.selectByPrimaryKey(currAccount.getPostTypeId());
        if (null != postType) {
            accountVO.setPostTypeName(postType.getDictName());
        }


        result.setData(accountVO);

        result.setMessage("获取账号详情成功.");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }


    /***
     * 验证原密码是否正确
     * @param password
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.CHECK, detail = "验证原密码是否正确")
    @ApiOperation(value = "验证原密码是否正确", notes = "验证原密码是否正确")
    @ApiImplicitParam(dataType = "String", name = "password", value = "原理账户密码", required = true)
    @GetMapping(value = "/verifyPwd")
    public ResponseEntity<HttpDataResult<Boolean>> verifyPwd(
            @RequestParam(value = "password") String password,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<Boolean> result = new HttpDataResult<>(request.getRequestURI());
        final TSysAccount currAccount = (TSysAccount) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_INFO.getKey());

        if(currAccount.getPassword().equals(PwdHashSaltUtils.againSha256Hex(currAccount.getAccount(),password.trim()))){
            result.setData(true);
        }else {
            result.setData(false);
        }

        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /***
     * 修改密码提交
     * @param password
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.UPDATE, detail = "修改密码提交")
    @ApiOperation(value = "修改密码提交", notes = "修改密码提交")
    @ApiImplicitParam(dataType = "String", name = "password", value = "修改账户新密码(无需sha256编码，需进行密码健壮性判断)", required = true)
    @PutMapping(value = "/modifyPwdSubmit")
    public ResponseEntity<HttpDataResult<TSysAccount>> modifyPwdSubmit(
            @RequestParam(value = "password") String password,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<TSysAccount> result = new HttpDataResult<>(request.getRequestURI());
        final TSysAccount currAccount = (TSysAccount) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_INFO.getKey());

        //密码健壮性判断
        if (CheckStrength.getPasswordLevel(password).equals(CheckStrength.LEVEL.EASY)){
            throw new CheckException("新密码过于简单,请重新设置！");
        }
        //校验修改后密码与原始密码是否一致
        if(currAccount.getPassword().equals(PwdHashSaltUtils.againSha256Hex(currAccount.getAccount(),password))){
            throw new CheckException("新密码不能与现密码一致，请重输!");
        }

        TSysAccount acc=new TSysAccount();
        acc.setAccountId(currAccount.getAccountId());
        acc.setPassword(PwdHashSaltUtils.againSha256Hex(currAccount.getAccount(),password));
        accountService.updateByPrimaryKeySelective(acc);

        currAccount.setPassword(password);
        request.getSession().setAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_INFO.getKey(), currAccount);

        result.setData(currAccount);
        result.setMessage("修改密码成功.");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }





//    /***
//     * 首次修改密码提交
//     * @param modifyPwdDO
//     * @param request
//     * @param response
//     * @return
//     * @throws Exception
//     */
//    @OperLog(module = MODULE, action = OperLogActionEnum.UPDATE, detail = "首次修改密码提交")
//    @ApiOperation(value = "首次修改密码提交", notes = "首次修改密码提交")
//    @ApiParam(type = "FirstModifyPwdDO", name = "modifyPwdDO", value = "当前用户首次修改密码提交对象", required = true)
//    @PutMapping(value = "/firstModifyPwdSubmit")
//    public ResponseEntity<HttpDataResult<TSysAccount>> firstModifyPwdSubmit(
//            @RequestBody @Validated FirstModifyPwdDO modifyPwdDO, BindingResult results,
//            HttpServletRequest request, HttpServletResponse response) throws Exception {
//        if (results.hasErrors()){
//            throw new CheckException(Objects.requireNonNull(results.getFieldError()).getDefaultMessage());
//        }
//
//        HttpDataResult<TSysAccount> result = new HttpDataResult<>(request.getRequestURI());
//        TSysAccount currAccount = (TSysAccount) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_INFO.getKey());
//
//        if (null!=modifyPwdDO.getTel() && !modifyPwdDO.getTel().equals(currAccount.getTel())){
//            String suffixKey="bindMobilePhone:"+modifyPwdDO.getTel();
//            if (!captchaRedisService.hasKeyCaptcha(suffixKey)) {
//                throw new CheckException("请先发送验证码进行手机号码验证！");
//            }
//            if (null==modifyPwdDO.getCaptcha() || "".equals(modifyPwdDO.getCaptcha().trim())){
//                throw new CheckException("请输入有效的验证码！");
//            }
//            String captcha=captchaRedisService.getCaptcha(suffixKey);
//            if (!captcha.equals(modifyPwdDO.getCaptcha())){
//                throw new CheckException("手机验证码错误，请确认！");
//            }
//        }
//        //密码健壮性判断
//        if (CheckStrength.getPasswordLevel(modifyPwdDO.getPassword()).equals(CheckStrength.LEVEL.EASY)){
//            throw new CheckException("新密码过于简单,请重新设置！");
//        }
//        //校验修改后密码与原始密码是否一致
//        if(currAccount.getPassword().equals(PwdHashSaltUtils.primitiveSha256Hex(currAccount.getAccount(),modifyPwdDO.getPassword()))){
//            throw new CheckException("新密码不能与现密码一致，请重输!");
//        }
//
//
//        currAccount=accountService.selectByPrimaryKey(currAccount.getAccountId());
//        currAccount.setTel(modifyPwdDO.getTel());
//        currAccount.setPassword(PwdHashSaltUtils.primitiveSha256Hex(currAccount.getAccount(),modifyPwdDO.getPassword().trim()));
//
//        accountService.updateByPrimaryKey(currAccount);
//
//
//        request.getSession().setAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_INFO.getKey(), currAccount);
//
//        result.setData(currAccount);
//        result.setMessage("修改密码成功.");
//        result.setStatus(HttpStatus.OK.value());
//        return new ResponseEntity<>(result, HttpStatus.OK);
//    }




    /***
     * 修改个人信息提交
     * @param accountDO
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.UPDATE, detail = "修改个人信息提交")
    @ApiOperation(value = "修改个人信息提交", notes = "修改个人信息提交")
    @ApiParam(type = "CurrentAccountDO", name = "accountDO", value = "当前用户信息修改提交对象", required = true)
    @PutMapping(value = "/modifyAccountSubmit")
    public ResponseEntity<HttpDataResult<TSysAccount>> modifyAccountSubmit(
            @RequestBody @Validated CurrentAccountDO accountDO, BindingResult results,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (results.hasErrors()){
            throw new CheckException(Objects.requireNonNull(results.getFieldError()).getDefaultMessage());
        }

        HttpDataResult<TSysAccount> result = new HttpDataResult<>(request.getRequestURI());
        TSysAccount currAccount = (TSysAccount) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_INFO.getKey());

//        if (null!=accountDO.getTel() && !accountDO.getTel().equals(currAccount.getTel())){
//            String suffixKey="bindMobilePhone:"+accountDO.getTel();
//            if (!captchaRedisService.hasKeyCaptcha(suffixKey)) {
//                throw new CheckException("请先发送验证码进行手机号码验证！");
//            }
//            if (null==accountDO.getCaptcha() || "".equals(accountDO.getCaptcha().trim())){
//                throw new CheckException("请输入有效的验证码！");
//            }
//            String captcha=captchaRedisService.getCaptcha(suffixKey);
//            if (!captcha.equals(accountDO.getCaptcha())){
//                throw new CheckException("手机验证码错误，请确认！");
//            }
//        }


        TSysAccount acc=new TSysAccount();
        acc.setAccountId(currAccount.getAccountId());
        acc.setRealName(accountDO.getRealName());
        acc.setTel(accountDO.getTel());
        acc.setEmail(accountDO.getEmail());

        String portraitFileId= saveTempFile(accountDO.getPortraitFileSet()!=null?accountDO.getPortraitFileSet():"currentAccountPortrait", request);
        if (null!=portraitFileId){
            //删除老图
            if (null!=currAccount.getPortraitFileId() && !"".equals(currAccount.getPortraitFileId().trim())){
                fileGenericStrategy.deleteFile(currAccount.getPortraitFileId());
            }
            acc.setPortraitFileId(portraitFileId);
        }

        accountService.updateByPrimaryKeySelective(acc);

        currAccount=accountService.selectByPrimaryKey(currAccount.getAccountId());
        request.getSession().setAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_INFO.getKey(), currAccount);

        result.setData(currAccount);
        result.setMessage("修改个人信息成功.");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }


    /***
     * 删除个人头像
     * @param request
     * @param response
     * @return
     */

    @OperLog(module = MODULE, action = OperLogActionEnum.DELETE, detail = "删除个人头像")
    @ApiOperation(value = "删除个人头像", notes = "删除个人头像")
    @DeleteMapping(value = "/delPortrait")
    public ResponseEntity<HttpDataResult<Boolean>> delPortrait(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<Boolean> result = new HttpDataResult<>(request.getRequestURI());
        TSysAccount currAccount = (TSysAccount) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_INFO.getKey());

        TSysAccount account=accountService.selectByPrimaryKey(currAccount.getAccountId());
        if (null!=account.getPortraitFileId() && !"".equals(account.getPortraitFileId())){
            fileGenericStrategy.deleteFile(account.getPortraitFileId().trim());
        }
        account.setPortraitFileId(null);
        accountService.updateByPrimaryKey(account);

        request.getSession().setAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_INFO.getKey(), account);
        if (request.getSession().getAttribute(SessionAttributeEnum.PORTRAIT_URL.getKey()) != null) {
            request.getSession().removeAttribute(SessionAttributeEnum.PORTRAIT_URL.getKey());
        }
        result.setData(true);
        result.setMessage("删除个人头像成功.");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /***
     * 保存上传的临时文件
     * @param fileSet
     * @param request
     * @return
     */
    private String saveTempFile(String fileSet, HttpServletRequest request){
        if (request.getSession().getAttribute(fileSet) != null) {
            LinkedList<FileMeta> fileMetaList = (LinkedList<FileMeta>) request.getSession().getAttribute(fileSet);
            request.getSession().removeAttribute(fileSet);


            if (null!=fileMetaList && !fileMetaList.isEmpty()) {
                FileMeta fileMeta = fileMetaList.getLast();
                File iconFile = new File(tmpPath + "//" + fileMeta.getSaveFilePath());
                JsonResult<Map> jsonResult = fileGenericStrategy.simpleFileUpload("accountPortrait", iconFile, fileMeta.getFileName());

                if (jsonResult.getSuccess()) {
                    return  (String) jsonResult.getData().get("fileId");
                }
            }
        }
        return null;
    }



//    /***
//     * 绑定手机号发送验证码
//     * @param tel
//     * @param request
//     * @param response
//     * @return
//     * @throws Exception
//     */
//    @OperLog(module = MODULE, action = OperLogActionEnum.CHECK, detail = "绑定手机号发送验证码")
//    @ApiOperation(value = "绑定手机号发送验证码", notes = "绑定手机号发送验证码")
//    @ApiImplicitParam(dataType = "String", name = "tel", value = "手机号码", required = true)
//    @PostMapping(value = "/bindMobilePhoneSendCaptcha")
//    public ResponseEntity<HttpResult> bindMobilePhoneSendCaptcha(
//            @RequestParam(value = "tel") String tel,
//            HttpServletRequest request, HttpServletResponse response) throws Exception {
//
//        HttpResult result = new HttpResult(request.getRequestURI());
//        TSysAccount currAccount = (TSysAccount) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_INFO.getKey());
//
//        if (!RegexKit.getMatcher(tel.trim(),RegexKit.REGEX_MOBILE_EXACT).matches()){
//            throw new CheckException("手机号码验证不符合规则,请确认！");
//        }
//
//        String code=null;
//        String suffixKey="bindMobilePhone:"+tel.trim();
//        if (captchaRedisService.hasKeyCaptcha(suffixKey)){
//
//            final LocalDateTime sendTime =captchaRedisService.getTime(suffixKey);
//            if (null!=sendTime) {
//                Duration duration = Duration.between(sendTime, LocalDateTime.now());
//                //三分钟内无法再试发送短信验证码
//                int threeMinutes = 3;
//                if (duration.toMinutes() <= threeMinutes) {
//                    throw new CheckException("获取短信验证码过于频繁，请三分钟后再试！");
//                }
//            }
//            Integer count=captchaRedisService.getCount(suffixKey);
//            //发送短信不能超过三次
//            int total=3;
//            if (null!=count && count>total){
//                throw new CheckException("获取短信验证码过于频繁，请30分钟后再试！");
//            }
//
//            code=captchaRedisService.getCaptcha(suffixKey);
//            captchaRedisService.refreshCaptcha(suffixKey);
//        }else {
//            code= CommonUtils.randomNumber(6);
//            captchaRedisService.setCaptcha(suffixKey,code);
//        }
//
//        if (null!=code) {
//            //发送短信验证码
//            aliSmsApiService.sendSms(tel.trim(), AlidayuSmsEnum.AUTHENTICATION_TEMPLATE_CODE.getValue(), ImmutableMap.of("code", code, "product", "手机号码绑定"));
//        }
//        result.setMessage("发送短信成功.");
//        result.setStatus(HttpStatus.OK.value());
//        return new ResponseEntity<>(result, HttpStatus.OK);
//    }


}
